/* @flow */

import Vue from 'core/index';
import config from 'core/config';
// extend 扩展对象.noop 空函数
import { extend, noop } from 'shared/util';
import { mountComponent } from 'core/instance/lifecycle';
import { devtools, inBrowser } from 'core/util/index';

import {
    query,
    mustUseProp,
    isReservedTag,
    isReservedAttr,
    getTagNamespace,
    isUnknownElement
} from 'web/util/index';

import { patch } from './patch';
import platformDirectives from './directives/index';
import platformComponents from './components/index';

// install platform specific utils
// Vue.config绑定一些方法
// 判断是否是关键属性(表单元素的input/checked/selected/muted )
// 如果是这些属性，设置el. 必须使用props设置属性(属性不能设置到标签上)
Vue.config.mustUseProp = mustUseProp;

// 判断是否为已知的标签，包括html标签和svg标签
Vue.config.isReservedTag = isReservedTag;

// 判断是否为 style/class 属性
Vue.config.isReservedAttr = isReservedAttr;

// 如果在svg标签map中全部返回 svg 字符串
Vue.config.getTagNamespace = getTagNamespace;

// 是否为未知的标签
Vue.config.isUnknownElement = isUnknownElement;

// install platform runtime directives & components
// 注册和平台相关的指令和组件。此处注册 v-model、v-show指令
// 注册了Transition、TransitionGroup组件。所有注册的组件都可在vue.options上访问到。
extend(Vue.options.directives, platformDirectives);
extend(Vue.options.components, platformComponents);

// install platform patch function
// patch 将虚拟dom转换为真实dom。判断是否为浏览器环境，如果是浏览器环境，则直接执行patch函数，将虚拟dom转为真实dom
Vue.prototype.__patch__ = inBrowser ? patch : noop;

// public mount method
// $mount渲染dom
Vue.prototype.$mount = function (el?: string | Element, hydrating?: boolean): Component {
    el = el && inBrowser ? query(el) : undefined;
    // mountComponent 渲染dom
    return mountComponent(this, el, hydrating);
};

// devtools global hook
/* istanbul ignore next */
if (inBrowser) {
    setTimeout(() => {
        if (config.devtools) {
            if (devtools) {
                devtools.emit('init', Vue);
            } else if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test') {
                console[console.info ? 'info' : 'log'](
                    'Download the Vue Devtools extension for a better development experience:\n' +
                        'https://github.com/vuejs/vue-devtools'
                );
            }
        }
        if (
            process.env.NODE_ENV !== 'production' &&
            process.env.NODE_ENV !== 'test' &&
            config.productionTip !== false &&
            typeof console !== 'undefined'
        ) {
            console[console.info ? 'info' : 'log'](
                `You are running Vue in development mode.\n` +
                    `Make sure to turn on production mode when deploying for production.\n` +
                    `See more tips at https://vuejs.org/guide/deployment.html`
            );
        }
    }, 0);
}

export default Vue;
